package com.fjwt.gz.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjwt.gz.core.cache.RedisUtil;
import com.fjwt.gz.db.bo.ActivityAwardAndSettingBo;
import com.fjwt.gz.db.bo.ActivityAwardBO;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.db.entity.*;
import com.fjwt.gz.db.vo.ActivityAwardVO;
import com.fjwt.gz.db.vo.CouponVO;
import com.fjwt.gz.service.activity.BaseActivityDTO;
import com.fjwt.gz.service.mapper.ActivityAwardMapper;
import com.fjwt.gz.util.PeriodUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 营销活动奖品对应表 服务实现类
 * </p>
 *
 * @author shiyonghao
 * @since 2025-04-09
 */
@Slf4j
@Service
public class ActivityAwardService extends ServiceImpl<ActivityAwardMapper, ActivityAwardEntity> {
    @Autowired
    private ActivityAwardMapper activityAwardMapper;
    @Autowired
    private AwardCouponService awardCouponService;
    @Autowired
    private AwardGoodsService awardGoodsService;
    @Autowired
    private AwardVirtualService awardVirtualService;
    @Autowired
    private AwardScoreService awardScoreService;
    @Autowired
    private AwardVirtualInsideService awardVirtualInsideService;
    @Autowired
    private ActivityService activityService;


    /**查询活动奖品(ActivityAward)和奖品对应的限制条件（awardSetting）**/

    public List<ActivityAwardAndSettingBo> getAwardAndSetting(Long activityId){
        List<ActivityAwardAndSettingBo> list = activityAwardMapper.getAwardAndSetting(activityId);
        if (ObjectUtils.isNotEmpty(list)) {
            Map<Integer, List<ActivityAwardAndSettingBo>> awardTypeMap = list.stream().collect(Collectors.groupingBy(ActivityAwardAndSettingBo::getAwardType));
            awardTypeMap.forEach((k, v) -> {
                Map<Long, ActivityAwardAndSettingBo> awardIdMap = v.stream().collect(Collectors.toMap(ActivityAwardAndSettingBo::getAwardId, Function.identity()));
                switch (k) {
                    case 0 :
                        List<AwardCouponEntity> awardCouponEntities = awardCouponService.listByIds(awardIdMap.keySet());
                        for (AwardCouponEntity awardCouponEntity : awardCouponEntities) {
                            ActivityAwardAndSettingBo activityAwardAndSettingBo = awardIdMap.get(awardCouponEntity.getCouponId());
                            activityAwardAndSettingBo.setAwardPrice(awardCouponEntity.getCouponPrice());
                            activityAwardAndSettingBo.setPayAuthId(awardCouponEntity.getPayAuthId());
                            activityAwardAndSettingBo.setEndTime(awardCouponEntity.getEndTime());
                        }
                        break;
                    case 1 :
                        List<AwardGoodsEntity> awardGoodsEntities = awardGoodsService.listByIds(awardIdMap.keySet());
                        for (AwardGoodsEntity awardGoodsEntity : awardGoodsEntities) {
                            ActivityAwardAndSettingBo activityAwardAndSettingBo = awardIdMap.get(awardGoodsEntity.getGoodsId());
                            activityAwardAndSettingBo.setAwardPrice(awardGoodsEntity.getGoodsPrice());
                        }
                        break;
                    case 2 :
                        List<AwardVirtualEntity> awardVirtualEntities = awardVirtualService.listByIds(awardIdMap.keySet());
                        for (AwardVirtualEntity awardVirtualEntity : awardVirtualEntities) {
                            ActivityAwardAndSettingBo activityAwardAndSettingBo = awardIdMap.get(awardVirtualEntity.getVirtualId());
                            // todo 使用到虚拟券属性在添加
                        }
                        break;
                    case 3 :
                        List<AwardScoreEntity> awardScoreEntities = awardScoreService.listByIds(awardIdMap.keySet());
                        for (AwardScoreEntity awardScoreEntity : awardScoreEntities) {
                            ActivityAwardAndSettingBo activityAwardAndSettingBo = awardIdMap.get(awardScoreEntity.getScoreId());
                            // todo 使用到积分奖品属性在添加
                            activityAwardAndSettingBo.setScoreValue(awardScoreEntity.getScoreValue());
                        }
                        break;
                    default:
                        break;
                }
            });
        }
        return list;
    }

    /**
     * 转换数据
     */
    public ActivityAwardVO toUserData(ActivityAwardBO activityAwardBO) {
        log.info("发券后返回用户的数据进来的参数是:{}", JSONUtil.toJsonStr(activityAwardBO));
        if(activityAwardBO==null) return null;
        ActivityAwardVO activityAwardVO = new ActivityAwardVO();
        activityAwardVO.setAwardId(activityAwardBO.getAwardId());
        activityAwardVO.setAwardName(activityAwardBO.getAwardName());
        activityAwardVO.setAwardType(activityAwardBO.getAwardType());
        activityAwardVO.setFansAwardId(activityAwardBO.getFansAwardId());
        log.info("发券后返回用户的数据:{}", JSONUtil.toJsonStr(activityAwardVO));
        return activityAwardVO;
    }

    /**
     * 减少库存
     */
    public Object reduceNum(Long awardId,int awardType) {
        Object successEntity = null;
        Boolean isUpdateSuccess = null;
        switch (awardType) {
            case Constants.AWARD.COUPON:
                AwardCouponEntity awardCouponEntity = awardCouponService.getById(awardId);
                if (awardCouponEntity.getCouponGet() < awardCouponEntity.getCouponNum()) {
                    awardCouponEntity.setCouponGet(awardCouponEntity.getCouponGet() + 1);
                    isUpdateSuccess = awardCouponService.updateById(awardCouponEntity);
                    if(isUpdateSuccess)successEntity=awardCouponEntity;
                }
                break;
            case Constants.AWARD.GOODS:
                AwardGoodsEntity awardGoodsEntity = awardGoodsService.getById(awardId);
                if (awardGoodsEntity.getGoodsGet() < awardGoodsEntity.getGoodsNum()) {
                    awardGoodsEntity.setGoodsGet(awardGoodsEntity.getGoodsGet() + 1);
                    isUpdateSuccess = awardGoodsService.updateById(awardGoodsEntity);
                    if(isUpdateSuccess)successEntity=awardGoodsEntity;
                }
                break;
            case Constants.AWARD.SCORE:
                AwardScoreEntity awardScoreEntity = awardScoreService.getById(awardId);
                if (awardScoreEntity.getScoreGet() < awardScoreEntity.getScoreNum() || awardScoreEntity.getScoreNum() == 0) {
                    awardScoreEntity.setScoreGet(awardScoreEntity.getScoreGet() + 1);
                    isUpdateSuccess = awardScoreService.updateById(awardScoreEntity);
                    if(isUpdateSuccess)successEntity=awardScoreEntity;
                }
                break;
            case Constants.AWARD.VIRTUAL_COUPON:
                AwardVirtualEntity awardVirtualEntity = awardVirtualService.getById(awardId);
                if (awardVirtualEntity.getGoodsGet() < awardVirtualEntity.getGoodsNum()) {
                    awardVirtualEntity.setGoodsGet(awardVirtualEntity.getGoodsGet() + 1);
                    isUpdateSuccess = awardVirtualService.updateById(awardVirtualEntity);
                    if(isUpdateSuccess)successEntity=awardVirtualEntity;
                }
                break;
            default:
                throw new BizException("奖品类型错误!");
        }
        if (isUpdateSuccess != null && !isUpdateSuccess) {
            throw new BizException("活动太火爆了，请稍后再试!");
        }
        log.info("奖品awardId:{}，awardType:{}，库存减去成功", awardId, awardType);
        return successEntity;
    }

    /**
     * 获取活动奖品---抽奖用
     */
    public List<ActivityAwardBO> getAwardList(List<ActivityAwardAndSettingBo> activityAwardList) {
        List<ActivityAwardBO> list = new ArrayList<>();
        for (ActivityAwardAndSettingBo entity : activityAwardList) {
            Long awardId = entity.getAwardId();
            switch (entity.getAwardType()) {
                case Constants.AWARD.COUPON:
                    AwardCouponEntity couponAwardEntity = awardCouponService.getById(awardId);
                    list.add(setAwardInfo(couponAwardEntity.getCouponId(), couponAwardEntity.getCouponName(), Constants.AWARD.COUPON,
                            entity.getAwardProbability(), couponAwardEntity.getCouponNum(), couponAwardEntity.getCouponGet(), null, null,
                            couponAwardEntity.getEndTime(), null, couponAwardEntity.getAvailableDays(), null,entity.getRemark(),
                            null, null));
                    break;
                case Constants.AWARD.GOODS:
                    AwardGoodsEntity goodsAwardEntity = awardGoodsService.getById(awardId);
                    list.add(setAwardInfo(goodsAwardEntity.getGoodsId(), goodsAwardEntity.getGoodsName(), Constants.AWARD.GOODS,
                            entity.getAwardProbability(), goodsAwardEntity.getGoodsNum(), goodsAwardEntity.getGoodsGet(), null, null,
                            goodsAwardEntity.getGoodsOverTime(), null, goodsAwardEntity.getGoodsOverDays(), null,entity.getRemark(),
                            null, null));
                    break;
                case Constants.AWARD.SCORE:
                    AwardScoreEntity scoreAwardEntity = awardScoreService.getById(awardId);
                    list.add(setAwardInfo(scoreAwardEntity.getScoreId(), scoreAwardEntity.getScoreName(), Constants.AWARD.SCORE, entity.getAwardProbability(),
                            scoreAwardEntity.getScoreNum(), scoreAwardEntity.getScoreGet(), scoreAwardEntity.getScoreValue(), scoreAwardEntity.getOverDays(),
                            scoreAwardEntity.getOverTime(), null, scoreAwardEntity.getOverDays(), scoreAwardEntity.getOverType(),entity.getRemark(),
                            null, null));
                    break;
//                case Constants.AWARD.VIRTUAL_COUPON:
//                    AwardVirtualEntity virtualCouponAwardEntity = awardVirtualService.getById(awardId);
//                    list.add(setAwardInfo(virtualCouponAwardEntity.getVirtualId(), virtualCouponAwardEntity.getn(), Constants.AWARD.VIRTUAL_COUPON,
//                            entity.getAwardProbability(), virtualCouponAwardEntity.getVirtualCouponNum(), virtualCouponAwardEntity.getVirtualCouponGet(), null, null,
//                            virtualCouponAwardEntity.getETime(), null, null, null,entity.getRemark(),
//                            null, null));
//                    break;
            }
        }

        return list;
    }

    /**
     * 设置奖品信息
     */
    private ActivityAwardBO setAwardInfo(Long awardId, String awardName, int awardType, int awardProbability, Integer awardNum,
                                         Integer awardGet, Integer scoreValue, Integer overDays, Date overTime, Integer isAllocation, Integer availableDays, Integer overType, String activityAwardRemark,
                                         Integer isLimitUser, String limitUserContent) {
        ActivityAwardBO activityAwardBo = new ActivityAwardBO();
        activityAwardBo.setAwardId(awardId);
        activityAwardBo.setAwardName(awardName);
        activityAwardBo.setAwardType(awardType);
        activityAwardBo.setAwardNum(awardNum);
        activityAwardBo.setAwardGet(awardGet);
        activityAwardBo.setAwardProbability(awardProbability);
        activityAwardBo.setScoreValue(scoreValue);
        activityAwardBo.setOverDays(overDays);
        activityAwardBo.setOverTime(overTime);
        activityAwardBo.setIsAllocation(isAllocation);
        activityAwardBo.setAvailableDays(availableDays);
        activityAwardBo.setOverType(overType);
        activityAwardBo.setActivityAwardRemark(activityAwardRemark);
        activityAwardBo.setIsLimitUser(isLimitUser);
        activityAwardBo.setLimitUserContent(limitUserContent);
        return activityAwardBo;
    }

    /**
     * 查询 越减越便宜活动卡券的剩余数量
     *
     * @param activityId 活动ID
     * @return
     */
    public ActivityAwardVO getActivityCouponNum(Long activityId) {
        // 查询活动奖品关联配置
        String activityNumberKey = String.format("%s%s:%s", Constants.REDIS_ACTIVITY.FILENAME, activityId, Constants.REDIS_ACTIVITY.NUMBER);
        ActivityAwardVO activityCouponNum = RedisUtil.getObject(activityNumberKey, ActivityAwardVO.class);
        if (activityCouponNum == null) {
            activityCouponNum = baseMapper.getActivityCouponNum(activityId);
            if (activityCouponNum != null) {
                RedisUtil.set(activityNumberKey, activityCouponNum, 24, TimeUnit.HOURS);
                log.info("活动卡券数量，从数据库加载到redis缓存中，redisKey:{},redisValue:{},redisOutTime:{},TimeUnit:{}", activityNumberKey, JSONUtil.toJsonStr(activityCouponNum), 24, "TimeUnit.HOURS");
            }
        }
        if (activityCouponNum == null) {
            throw new BizException("该活动未配置奖品！");
        }
        if (activityCouponNum.getPeriodType() != 0) {
            final Integer periodType = activityCouponNum.getPeriodType();//限制周期类型
            int historyPeriod = activityCouponNum.getCurrentPeriodType();//当前类型  第几天 第几周
            final int periodTimes = activityCouponNum.getPeriodTimes();//限制周期次数
            int currentPeriod = PeriodUtil.getPeriod(periodType);
            if (currentPeriod != historyPeriod) {
                activityCouponNum.setCouponNum(periodTimes);
                activityCouponNum.setCouponGet(0);
            } else {
                activityCouponNum.setCouponNum(periodTimes);
                activityCouponNum.setCouponGet(activityCouponNum.getCurrentPeriodTimes());
            }
            log.info("当前周期：{}，历史周期：{}", currentPeriod, historyPeriod);
        }
        return activityCouponNum;
    }

    /**
     * 查询 活动卡券的剩余数量【公共可用，目前先加卡券的类型】
     * @return
     */
    public ActivityAwardVO getActivityAwardNum(Long activityId,Long awardId,Long awardType) {

        ActivityEntity activityEntity = activityService.getById(activityId);
        if (activityEntity == null) {
            throw new BizException("当前活动不存在");
        }
        if (activityEntity.getState()!=4){
            throw new BizException("当前活动已下线");
        }

        if (DateUtil.compare(new Date(),activityEntity.getEndTime())!=-1){
            throw new BizException("当前活动已下线");
        }
        ActivityAwardVO activityCouponNum = new ActivityAwardVO();
        if (awardType == 0){
            //卡券类型
            activityCouponNum = baseMapper.getActivityAwardNum(activityId,awardId);
        }
        return activityCouponNum;
    }

    /**
     * 奖品列表
     */
    public List<ActivityAwardVO> queryList(Long activityId) {
        List<ActivityAwardVO> activityAwardList = this.baseMapper.queryList(activityId);
        for (ActivityAwardVO item : activityAwardList) {
            Long awardId = item.getAwardId();
            switch (item.getAwardType()) {
                case Constants.AWARD.COUPON:
                    AwardCouponEntity couponAwardEntity = awardCouponService.getById(awardId);
                    item.setAwardName(couponAwardEntity.getCouponName());
                    item.setAwardPrice(couponAwardEntity.getCouponPrice());
                    item.setPayAmount(couponAwardEntity.getPayAmount());
                    LambdaQueryWrapper<ActivityAwardEntity> gw = ActivityAwardEntity.gw();
                    gw.eq(ActivityAwardEntity::getAwardId, couponAwardEntity.getCouponId());
                    gw.eq(ActivityAwardEntity::getAwardType, Constants.AWARD.COUPON);
                    ActivityAwardEntity activityAwardEntity = getOne(gw);
                    item.setRemark(activityAwardEntity.getRemark());
                    break;
                case Constants.AWARD.GOODS:
                    AwardGoodsEntity goodsAwardEntity = awardGoodsService.getById(awardId);
                    item.setAwardName(goodsAwardEntity.getGoodsName());
                    item.setAwardPrice(goodsAwardEntity.getGoodsPrice());
                    item.setAwardImg(goodsAwardEntity.getGoodsImgBanner());
                    break;
                case Constants.AWARD.SCORE:
                    AwardScoreEntity scoreAwardEntity = awardScoreService.getById(awardId);
                    item.setAwardName(scoreAwardEntity.getScoreName());
                    item.setAwardPrice(scoreAwardEntity.getScoreValue());
                    break;
                case Constants.AWARD.VIRTUAL_COUPON:
                    AwardVirtualEntity virtualCouponAwardEntity = awardVirtualService.getById(awardId);
                    AwardVirtualInsideEntity awardVirtualInsideEntity = awardVirtualInsideService.getById(virtualCouponAwardEntity.getVirtualInsideId());
                    item.setAwardName(awardVirtualInsideEntity.getGoodsName());
                    break;
            }
        }
        return activityAwardList;
    }

    /**
     * 查询奖品配置活动信息及app信息
     * @param awardId
     * @param awardType
     * @return
     */
    public ActivityAwardAndSettingBo getActivityAndApp(Long awardId, Integer awardType) {
        return baseMapper.selectActivityAndApp(awardId, awardType);
    }

    /**
     * 获取活动已绑定的卡券信息
     * @param activityIds
     * @return
     */
    public List<CouponVO> getCouponByActivityIds(Collection<Long> activityIds) {
        return baseMapper.getCouponByActivityIds(activityIds);
    }

    /**
     * 校验奖品状态是否正常
     * @param activityAwardList
     * @return
     */
    @Transactional
    public void checkActivityAward(List<BaseActivityDTO.ActivityAward> activityAwardList) {
        Map<Integer, List<Long>> awardMap = activityAwardList.stream().collect(Collectors.groupingBy(BaseActivityDTO.ActivityAward::getAwardType,
                Collectors.mapping(BaseActivityDTO.ActivityAward::getAwardId, Collectors.toList())));
        awardMap.forEach((awardType, awardIds) -> {
            switch (awardType) {
                case Constants.AWARD.COUPON -> {
                    List<AwardCouponEntity> list = awardCouponService.listByIds(awardIds);
                    if (ObjectUtils.isEmpty(list) || list.size() != awardIds.size()) {
                        throw new BizException("活动绑定奖品异常，请检查");
                    }
                    awardCouponService.lambdaUpdate()
                            .in(AwardCouponEntity::getCouponId, awardIds)
                            .set(AwardCouponEntity::getState, Constants.AWARD_STATE.ONLINE)
                            .update();
                }
                case Constants.AWARD.GOODS -> {
                    List<AwardGoodsEntity> list = awardGoodsService.listByIds(awardIds);
                    if (ObjectUtils.isEmpty(list) || list.size() != awardIds.size()) {
                        throw new BizException("活动奖品信息异常，请检查");
                    }
                    awardGoodsService.lambdaUpdate()
                            .in(AwardGoodsEntity::getGoodsId, awardIds)
                            .set(AwardGoodsEntity::getState, Constants.AWARD_STATE.ONLINE)
                            .update();
                }
                case Constants.AWARD.SCORE -> {
                    List<AwardScoreEntity> list = awardScoreService.listByIds(awardIds);
                    if (ObjectUtils.isEmpty(list) || list.size() != awardIds.size()) {
                        throw new BizException("活动奖品信息异常，请检查");
                    }
                    awardScoreService.lambdaUpdate()
                            .in(AwardScoreEntity::getScoreId, awardIds)
                            .set(AwardScoreEntity::getState, Constants.AWARD_STATE.ONLINE)
                            .update();
                }
                case Constants.AWARD.VIRTUAL_COUPON -> {
                    List<AwardVirtualEntity> list = awardVirtualService.listByIds(awardIds);
                    if (ObjectUtils.isEmpty(list) || list.size() != awardIds.size()) {
                        throw new BizException("活动奖品信息异常，请检查");
                    }
                    awardVirtualService.lambdaUpdate()
                            .in(AwardVirtualEntity::getVirtualId, awardIds)
                            .set(AwardVirtualEntity::getState, Constants.AWARD_STATE.ONLINE)
                            .update();
                }
                default -> throw new BizException("活动配置奖品类型有误");
            }
        });
    }
}
